package ai.perception;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;

import simulator.mv.ShapeBean;

public class Perceptor {
	//Constants:
	private final int FAR_THRESHOLD = 1000;
	private final int MIDDLE_THRESHOLD = 2000;
	
	private final int CENTER_THRESHOLD = 10;
	//Attributes:
	private int width,height;
	//Constructor:
	public Perceptor(int width, int height){
		this.width = width;
		this.height = height;
	}
	//Methods:
	public ShapeRelativePositionIdentifier getLocationBetween(ShapeBean a){
		ShapeBean shape = new ShapeBean();
		shape.setRectangle(new Rectangle(new Point((this.width/2)-(CENTER_THRESHOLD/2),(this.height/2)-(CENTER_THRESHOLD/2)),new Dimension(CENTER_THRESHOLD,CENTER_THRESHOLD)));
		return this.getLocationBetween(a, shape);
	}
	/**
	 * This function allows to know where is "a" considering "b" as the center.
	 * @param a
	 * @param b
	 * @return Relative position.
	 */
	public ShapeRelativePositionIdentifier getLocationBetween(ShapeBean a, ShapeBean b){
		int horizontalLocation,verticalLocation,proximityA,proximityB;
		Rectangle r1,r2;
		r1 = a.getRectangle();
		r2 = b.getRectangle();
		//Calculating Proximity:
		proximityA = this.getProximity((int)r1.getWidth(),(int)r1.getHeight());
		proximityB = this.getProximity((int)r2.getWidth(),(int)r2.getHeight());
		//Calculating horizontal location:
		horizontalLocation = this.getHorizontalRelativeMeasure((int)r1.getCenterX(),(int)r2.getCenterX());
		//Calculating vertical location:
		verticalLocation = this.getVerticalRelativeMeasure((int)r1.getCenterY(),(int)r2.getCenterY());
		ShapeRelativePositionIdentifier positionIdentifier = new ShapeRelativePositionIdentifier(a,b,horizontalLocation,verticalLocation,proximityA,proximityB);
		return positionIdentifier;
	}
	/**
	 * This function allows to transform an absolute measure into a relative one.
	 * @param d
	 * @return Relative distance.
	 */
	private int getProximity(int w,int h){
		int area = w*h;
		if((area >= 0) && (area <= this.FAR_THRESHOLD)){
			return RelativePosition.FAR;
		}else if((area > this.FAR_THRESHOLD) && (area <= this.MIDDLE_THRESHOLD)){
			return RelativePosition.MIDDLE;
		}else if(area > this.MIDDLE_THRESHOLD){
			return RelativePosition.NEAR;
		}else{
			return RelativePosition.NONE;
		}
	}
	/**
	 * This function allows to transform an absolute horizontal position, i.e. X, into a relative one.
	 * @param currentX
	 * @param xBasis
	 * @return Relative distance.
	 */
	private int getHorizontalRelativeMeasure(int currentX,int xBasis){
		if(currentX < (xBasis-this.CENTER_THRESHOLD)){
			return RelativePosition.LEFT;
		}else if((currentX >= (xBasis-this.CENTER_THRESHOLD)) && (currentX <= (xBasis+this.CENTER_THRESHOLD))){
			return RelativePosition.CENTER;
		}else if(currentX > (xBasis+this.CENTER_THRESHOLD)){
			return RelativePosition.RIGHT;
		}else{
			return RelativePosition.NONE;
		}
	}
	/**
	 * This function allows to transform an absolute vertical position, i.e. Y, into a relative one.
	 * @param currentY
	 * @param yBasis
	 * @return Relative distance.
	 */
	private int getVerticalRelativeMeasure(int currentY,int yBasis){
		if(currentY < (yBasis-this.CENTER_THRESHOLD)){
			return RelativePosition.UP;
		}else if((currentY >= (yBasis-this.CENTER_THRESHOLD)) && (currentY <= (yBasis+this.CENTER_THRESHOLD))){
			return RelativePosition.CENTER;
		}else if(currentY > (yBasis+this.CENTER_THRESHOLD)){
			return RelativePosition.DOWN;
		}else{
			return RelativePosition.NONE;
		}
	}
}
